// Events.js

// Functions starting with "Client_" are called to from within the client application.
// Functions starting with "Server_" are called remotely by the server.

// "Me" Imports- (Note: "Me" is imported as the self container. So instead of calling Me.alert("popup!"); you can just call alert("popup!"); )
//  [function] bytesToInt(str) - Deserializes an integer.
//  [function] dataGram(objectID, timeStamp, command, streamID, data) - Generates an rtmp datagram.
//  [function] getWebpage(url) - Gets the contents of a webpage.
//  [function] htmlDecode(htmlData) - Decodes html data.
//  [function] htmlEncode(htmlData) - Encodes html data.
//  [function] intToBytes(intValue, bytesTotal) - Serializes an integer.
//  [function] loadFile(fileName) - Gets the contents of a local file.
//  [function] numberDeserialize(str) - Deserializes a double value.
//  [function] numberSerialize(num) - Serializes a double value.
//  [function] randomNumber(min, max) - Returns a random number within a specified range.
//  [function] randomTimeStamp() - Returns random timestamp integer.
//  [function] stringReplace(str, findStr, replaceStr) - Replaces characters in a string.
//  [function] stringSerialize(str) - Serializes a string. (string length and string)
//  [function] unicodeToUtf8(str) - Converts unicode string to UTF-8.
//  [function] urlEncode(urlParam) - Encodes string for use in a url.
//  [function] utf8ToUnicode(str) - Converts UTF-8 string to unicode.
//  [sub] addColorText(msg, fontColor, newLine) - Adds text to lobby chat with specified font color.
//  [sub] addFontText(msg, font, fontColor, fontSize, isBold, isItalics, isUnderline, newLine) - Adds text to lobby chat with specified font settings.
//  [sub] addText(msg, newLine) - Adds text to lobby chat.
//  [sub] alert(obj) - Simple alert box.
//  [sub] connect(serverIP) - Connect directly to an ip.
//  [sub] doClose() - Closes connection stream. "Client_rtmpClosed" will also be called in return.
//  [sub] doJoin(roomID, roomName, roomPass) - Join a specified groupchat room.
//  [sub] doJoinLive(stickamURL) - Join a live room.
//  [sub] doLogin(email, pass) - Login to http.
//  [sub] getRoomlist() - Retrieves roomlist.
//  [sub] invertRGB() - Invert chat and userlist colors.
//  [sub] playSound(fileName) - Plays sound.
//  [sub] privateMessage(userID, msg, font, fontColor, fontSize, isBold, isItalics, isUnderline) - Displays an incoming private message. (only meant to be used by "Server_doMessage")
//  [sub] resetFontAndName() - Resets your font and display name.
//  [sub] sendData(data) - Sends raw data to the TCP stream.
//  [sub] setDisplayName(displayName) - Set your display name.
//  [sub] setStatus(msg) - Set a message on the client's status bar.
//  [sub] setTimeout(script, millisecs) - Wait to execute code. (example: setTimeout("alert(1)", 1000); )
//  [sub] stealFontAndName(userID) - Steals the stored font and display name of a specified user.

// "MyVars" Imports-
//  [var] currentDirectory - Current program directory.
//  [var] font, fontBold, fontColor, fontItalics, fontSize, fontUnderline - Personal font settings.
//  [var] inRoom - Declares whether you are presently in a room. (true/false)
//  [var] loginEmail, loginPass, loginUserID, loginUserName, loginWebID - Login parameters
//  [var] myUserID, myUserName, myScreenName - Personal user parameters when present in a room.
//  [var] roomID, roomIP, roomName, roomPass - Room parameters.
//  [var] selectedUser - UserID of the user currently selected on the room userlist.

// "Roomlist" Imports-
//  [var] created, id, isFlagged, isPrivate, isProtected, name, population - paramTypes
//  [var] selectedIndex - Last selected room index on roomlist.
//  [var] total - Total number of rooms.
//  [function] getParam(index, paramType) - Gets a roomlist param.
//  [sub] add(name, id, population, created, isPrivate, isProtected, isFlagged) - Adds room to roomlist.
//  [sub] clear() - Clears entire roomlist.

// "Userlist" Imports-
//  [var] componentBit, font, fontBold, fontColor, fontItalics, fontSize, fontUnderline, id, isModerator, isOwner, isVideo, langID, screenName, sessionType, userID, userName, userType - paramTypes
//  [var] total - Total number of users.
//  [function] getParam(index, paramType) - Gets a userlist param.
//  [add] add(userID, id, userName, screenName, isVideo, isModerator, isOwner, userType, sessionType, langID, componentBit) - Adds user to userlist.
//  [sub] clear() - Clears entire userlist.
//  [sub] remove(userID) - Removes user from the userlist.
//  [sub] updateFont(userID, font, fontColor, fontSize, isBold, isItalics, isUnderline) - Remembers user's font parameters.

// "Core.js" Imports-
//  [function] amfDeserialize(dataObj) - Deserializes an AMF value.
//  [function] amfObjectDeserialize(dataObj - Deserializes an AMF object.
//  [function] amfSerialize(obj) - Serializes a JavaScript object into an AMF object.
//  [function] asc(str) - Gets first charCode in a unicode string.
//  [function] chr(charCode) - Generates a unicode character.
//  [function] getAmfString(dataObj) - Deserializes AMF string.
//  [function] getObjectByType(obj, typeOf) - Gets object by type in an object array.
//  [function] invoke(objArray) - Generates AMF object array to be used in an invoke.
//  [function] parseInvoke(dataObj) - Deserializes AMF invoke into an object array.
//  [function] properBoolean(obj) - Returns a proper boolean value from any object.
//  [sub] debugObject(functionName, msgObj) - Lists a function with it's object parameters in the lobby chat.
//  [sub] doServer(msgObj) - Invoke the "doServer" function on the server.


// stickam client loaded.
function Client_applicationLoaded() {

}

// execute script on the server
// this function is considered obsolete
function Client_executeServerScript(scriptStr) {
	sendData(dataGram(3, randomTimeStamp(), 20, 0, invoke(["eval", 1, 0, scriptStr, 1])));
}

// kicking user.
function Client_kickUser(userID) {
	var msgObj = new Object();
	msgObj.event = "doRestrict";
	msgObj.type = "kick";
	msgObj.to = userID;
	if (MyVars.myUserID) {
		msgObj.from = MyVars.myUserID;
	} else {
		msgObj.from = MyVars.myScreenName;
		addColorText("Kicking from different userID " + MyVars.myScreenName + "...", "Green", true);
	}
	doServer(msgObj);
}

// logged in to http, or failed.
function Client_loggedIn(isSuccess) {

}

// logging in to http, return true to proceed.
function Client_loggingIn() {
	return true;
}

// make/unmake moderator.
function Client_makeModerator(userID) {
	var msgObj = new Object();
	if (Userlist.getParam(userID, Userlist.isModerator))
		msgObj.event = "unMakeModerator";
	else
		msgObj.event = "makeModerator";
	msgObj.to = userID;
	msgObj.from = MyVars.myUserID;
	doServer(msgObj);
}

// parse retrieved roomlist.
function Client_parseRoomlist(roomlistData) {
	Roomlist.clear();
	var currentRoom;
	for (var i in roomlistData) {
		currentRoom = roomlistData[i];
		Roomlist.add(utf8ToUnicode(currentRoom.name), currentRoom.roomId, currentRoom.inRoom, currentRoom.created, currentRoom.private, currentRoom.protected, currentRoom.flagged);
	}
}

// retrieving host id, return true to proceed.
function Client_retrievingHostID() {
	return true;
}

// failed to retrieve host id.
function Client_retrievingHostIDFailed() {

}

// retrieving room ip, return true to proceed.
function Client_retrievingRoomIP() {
	return true;
}

// failed to retrieve room ip, cannot connect.
function Client_retrievingRoomIPFailed() {

}

// roomlist retrieved and parsed, or failed.
function Client_roomlistRetrieved(isSuccess) {

}

// rtmp connection closed.
function Client_rtmpClosed() {
	MyVars.inRoom = false;
}

// rtmp connection success.
function Client_rtmpConnected() {

}

// room ip retrieved. connecting to room, return true to proceed.
function Client_rtmpConnecting() {
	return true;
}

// rtmp data arrival from server.
function Client_rtmpDataArrival(command, data) {
	if (ShowingData)
		addColorText("Showing Command: " + command + "\r\nData: " + stringReplace(data, chr(0), "."), "Blue", true);
	var dataObj = {data:data};
	switch (command) {
	case 4: // ping
		if (data.substr(0,2) == chr(0) + chr(6))
			sendData(dataGram(2, randomTimeStamp(), 4, 0, chr(0) + chr(7) + data.substr(2)));
	break;
	case 19: // shared object
		var dataLen;
		var dataType;
		var sharedObjectPath = getAmfString(dataObj);
		dataObj.data = dataObj.data.substr(12);
		while (dataObj.data.length) {
			dataType = asc(dataObj.data.substr(0,1));
			dataLen = bytesToInt(dataObj.data.substr(1,4));
			var dataObj2 = {data:dataObj.data.substr(5, dataLen)};
			dataObj.data = dataObj.data.substr(dataLen + 5);
			switch (dataType) {
			case 4: // create object, presumably always userid to add to userlist or modify userlist.
				var userID = getAmfString(dataObj2);
				var userObj = amfDeserialize(dataObj2);
				if (userObj.userID != undefined) {
					if (userObj.userType == "200")
						userObj.userID = "globalcount";
					userObj.componentBit = "";
					if (userObj.screenName == undefined || userObj.screenName == "")
						userObj.screenName = userObj.userName;
					if (userObj.isModerator == undefined)
						userObj.isModerator = false;
					if (userObj.userID == MyVars.hostID)
						userObj.isOwner = true;
					Userlist.add(userObj.userID, userObj.id, userObj.userName, userObj.screenName, userObj.isVideo, userObj.isModerator, userObj.isOwner, userObj.userType, userObj.sessionType, userObj.langID, userObj.componentBit);
				}
			break;
			case 6: // invoke
				var objArray = parseInvoke(dataObj2);
				//debugObject(getObjectByType(objArray, "string"), getObjectByType(objArray, "object"));
				ScriptControl.CodeObject["Server_" + getObjectByType(objArray, "string")](getObjectByType(objArray, "object"));
			break;
			case 9: // delete object, presumably always userid to delete from userlist.
				var userID = getAmfString(dataObj2);
				if (userID != MyVars.myUserID)
					Userlist.remove(userID);
			break;
			default: // unhandled shared object datatype
				if (dataType != 8 && dataType != 11)
					addColorText("Unhandled shared object.\r\ndataType: " + dataType + "\r\nData: " + stringReplace(dataObj2.data, chr(0), "."), "Red", true);
			}
		}
	break;
	case 20: // invoke call
		var objArray = parseInvoke(dataObj);
		//debugObject(getObjectByType(objArray, "string"), getObjectByType(objArray, "object"));
		ScriptControl.CodeObject["Server_" + getObjectByType(objArray, "string")](getObjectByType(objArray, "object"));
	break;
	default: // unhandled rtmp command
		addColorText("Unhandled Command: " + command + "\r\nData: " + stringReplace(data, chr(0), "."), "Blue", true);
	}
}

// rtmp handshake reply arrives, send handshakeData followed by connection request.
function Client_rtmpHandshakeReply(handshakeData) {
	if (MyVars.roomType == "group") {
		var msgObj = new Object();
		msgObj.app = "video_chat2_stickam_room/" + MyVars.roomID;
		msgObj.flashVer = "WIN 9,0,124,0";
		msgObj.swfUrl = "http://player.stickam.com/flash/stickam/stickam_chat_room.swf?ver=2.2.52";
		msgObj.tcUrl = "rtmp://" + MyVars.roomIP + "/video_chat2_stickam_room/" + MyVars.roomID;
		msgObj.fpad = false;
		msgObj.capabilities = 15;
		msgObj.audioCodecs = 1639;
		msgObj.videoCodecs = 252;
		msgObj.videoFunction = true;
		msgObj.pageUrl = "http://www.stickam.com/member/loadChatRoom.do?roomId=" + MyVars.roomID;
		var msgObj2 = new Object();
		msgObj2.userType = "205";
		msgObj2.sessionType = "115";
		msgObj2.appID = "1700";
		msgObj2.langID = "en";
		msgObj2.webID = MyVars.loginWebID;
		if (MyVars.roomPass != "")
			msgObj2.password = MyVars.roomPass;
		msgObj2.componentBit = undefined;
		msgObj2.loginType = "355";
		msgObj2.siteID = "1015547";
	} else if (MyVars.roomType == "live") {
		addColorText("Joining a live chat (" + MyVars.roomIP + ", " + MyVars.roomID + ")...", "Green", true);
		var msgObj = new Object();
		msgObj.app = "video_chat2_stickam/" + MyVars.roomID;
		msgObj.flashVer = "WIN 10,0,22,87";
		msgObj.swfUrl = "http://player.stickam.com/flash/stickam/stickam_chat_open.swf?ver=2.0.41"
		msgObj.tcUrl = "rtmp://" + MyVars.roomIP + "/video_chat2_stickam/" + MyVars.roomID;
		msgObj.fpad = false;
		msgObj.capabilities = 15;
		msgObj.audioCodecs = 1639;
		msgObj.videoCodecs = 252;
		msgObj.videoFunction = 1;
		msgObj.pageUrl = "http://www.stickam.com/largeChatNew.do?uId=" + MyVars.hostID;
		msgObj.objectEncoding = 0;
		//var liveType = 0;
		var msgObj2 = new Object();
		//if (liveType == 0) {
		msgObj2.channelSeq = null;
		msgObj2.playerType = "internal";
		msgObj2.sessionType = "115";
		msgObj2.serviceName = "stickam";
		msgObj2.appID = 1700;
		msgObj2.userType = "205";
		msgObj2.siteID = "1015547";
		msgObj2.webID = MyVars.loginWebID;
		msgObj2.componentBit = "3";
		msgObj2.langID = "jp";
		msgObj2.loginType = "355";
		//} else if (liveType == 1) {
		//	msgObj2.screenName = MyVars.myScreenName;
		//	msgObj2.playerType = "internal";
		//	msgObj2.webID = null;
		//	msgObj2.appID = 1700;
		//	msgObj2.componentBit = "3";
		//	msgObj2.serviceName = "stickam";
		//	msgObj2.loginType = "355";
		//	msgObj2.channelSeq = null;
		//	msgObj2.sessionType = "115";
		//	msgObj2.siteID = "1015547";
		//	msgObj2.userType = "204";
		//	msgObj2.langID = "en";
		//}
	}
	sendData(handshakeData + dataGram(3, 0, 20, 0, invoke(["connect", 1, msgObj, msgObj2])));
}

// send chat message.
function Client_sendChatMessage(msg) {
	var msgObj = new Object();
	msgObj.type = "1";
	msgObj.trans = 0;
	msgObj.event = "chatMsg";
	if (MyVars.myScreenName != "")
			if(MyVars.roomType == "group")
				msgObj.screenName = MyVars.myScreenName;
	msgObj.msg = msg;
	msgObj.channel = MyVars.roomID;
	if (MyVars.fontBold)
		msgObj.isBold = true;
	if (MyVars.fontItalics)
		msgObj.isItalics = true;
	if (MyVars.fontUnderline)
		msgObj.isUnderline = true;
	msgObj.fontColor = MyVars.fontColor;
	msgObj.fontSize = MyVars.fontSize;
	msgObj.font = MyVars.font;
	msgObj.from = MyVars.myUserID;
	msgObj.to = "all";
	doServer(msgObj);
}

// send private chat message.
function Client_sendPrivateMessage(userID, msg) {
	var msgObj = new Object();
	if (MyVars.fontBold)
		msgObj.isBold = true;
	if (MyVars.fontItalics)
		msgObj.isItalics = true;
	if (MyVars.fontUnderline)
		msgObj.isUnderline = true;
	msgObj.fontColor = MyVars.fontColor;
	msgObj.fontSize = MyVars.fontSize;
	msgObj.font = MyVars.font;
	msgObj.event = "doMessage";
	msgObj.type = "secretMsg";
	msgObj.to = userID;
	msgObj.from = MyVars.myUserID;
	msgObj.msg = msg;
	msgObj.m_format = " ";
	msgObj.n_format = " ";
	doServer(msgObj);
}

// send ping to rtmp server to maintain connection. client will call to this event every XX seconds.
function Client_sendPing() {
	var msgObj = new Object();
	msgObj.event = "pingToS";
	msgObj.type = "ping to";
	doServer(msgObj);
}

// "_error" invoke from server.
function Server__error(msgObj) {
	addColorText("Connection error! [Code: " + msgObj.code + ", Description: " + msgObj.description + "]", "Red", true);
}

// "_result" invoke from server.
function Server__result(msgObj) {
	switch (msgObj.level) {
	case "status":
		if (msgObj.code == "NetConnection.Connect.Success") {
			var msgObj2 = new Object();
			msgObj2.show = false;
			msgObj2.event = "setAvatar";
			sendData(dataGram(3, randomTimeStamp(), 20, 0, invoke(["doServer", 0, null, msgObj2])) +
			dataGram(3, randomTimeStamp(), 19, 0, stringSerialize("private/app_so") + XX + XX + XX + chr(1) + XX) +
			dataGram(3, randomTimeStamp(), 19, 0, stringSerialize("private/users_so") + XX + XX + XX + chr(1) + XX));
			MyVars.inRoom = true;
			setStatus("You are now in " + MyVars.roomName + ".");
		}
	}
}

// "chatMsg" invoke from server.
function Server_chatMsg(msgObj) {
	if (msgObj.font == "_sans")
		msgObj.font = "Arial";
	if (msgObj.from != MyVars.myUserID)
		Userlist.updateFont(msgObj.from, msgObj.font, msgObj.fontColor, msgObj.fontSize, properBoolean(msgObj.isBold), properBoolean(msgObj.isItalics), properBoolean(msgObj.isUnderline));
	var screenName;
	if (msgObj.screenName != undefined)
		screenName = msgObj.screenName
	else
		screenName = Userlist.getParam(msgObj.from, Userlist.screenName);
	if (!Userlist.getParam(msgObj.from, Userlist.isIgnored)) {
		addFontText(screenName + ": ", "Arial", msgObj.fontColor, 12, false, false, false, true);
		addFontText(msgObj.msg, msgObj.font, msgObj.fontColor, msgObj.fontSize, properBoolean(msgObj.isBold), properBoolean(msgObj.isItalics), properBoolean(msgObj.isUnderline), false);
		if (msgObj.isBuffer != true) {
			msgObj.msgLower = msgObj.msg.toLowerCase();
			Server_msgCmds(msgObj);
		}
	}
}

// "close" invoke from server.
function Server_close(msgObj) {
	addColorText("Server wants client to kill connection.", "Red", true);
}

// "doClient" invoke from server.
function Server_doClient(msgObj) {
	if (msgObj.event != "doClient")
		ScriptControl.CodeObject["Server_" + msgObj.event](msgObj);
}

// "doDisconnect" invoke from server.
function Server_doDisconnect(msgObj) {
	if (msgObj.type == "kick") {
		var remoteUserName = Userlist.getParam(msgObj.from, Userlist.screenName);
		addColorText("You have been kicked by " + remoteUserName + ".", "Red", true);
	} else {
		addColorText("Disconnect invoke received. Type: " + msgObj.type, "Red", true);
	}
}

// "doMessage" invoke from server.
function Server_doMessage(msgObj) {
	if (msgObj.type == "secretMsg" && msgObj.from != MyVars.myUserID) {
		if (msgObj.font == "_sans")
			msgObj.font = "Arial";
		Userlist.updateFont(msgObj.from, msgObj.font, msgObj.fontColor, msgObj.fontSize, msgObj.isBold, msgObj.isItalics, msgObj.isUnderline);
		if (!Userlist.getParam(msgObj.from, Userlist.isIgnored)) {
			privateMessage(msgObj.from, msgObj.msg, msgObj.font, msgObj.fontColor, msgObj.fontSize, properBoolean(msgObj.isBold), properBoolean(msgObj.isItalics), properBoolean(msgObj.isUnderline));
			msgObj.msgLower = msgObj.msg.toLowerCase();
			Server_msgCmds(msgObj);
		}
	} else if (msgObj.type == "gotFlag") {
		addColorText("You have been flagged by " + Userlist.getParam(msgObj.from, Userlist.screenName) + ".", "Blue", true);
	} else {
		addColorText("Unhandled doMessage type, \"" + msgObj.type + "\".", "Red", true);
	}
}

// "enableFeaturedVideo" invoke from server.
function Server_enableFeaturedVideo() {

}

// "enableModerator" invoke from server.
function Server_enableModerator() {

}

// "endViewerVideo" invoke from server.
function Server_endViewerVideo(msgObj) {

}

// "gotOneToOneRequest" invoke from server.
function Server_gotOneToOneRequest(msgObj) {
	addColorText("Received invite from " + Userlist.getParam(msgObj.from, Userlist.screenName) + ". Sending malicious accept response.", "Blue", true);
}

// "join" invoke from server.
function Server_join(msgObj) {
	var screenName;
	if (msgObj.from == MyVars.myUserID)
		screenName = MyVars.myUserName;
	else
		screenName = Userlist.getParam(msgObj.from, Userlist.screenName);
	addText("* " + screenName + " joined the room.", true);

}

// "left" invoke from server.
function Server_left(msgObj) {
	addText("* " + Userlist.getParam(msgObj.from, Userlist.screenName) + " left the room.", true);
}

// "moderatorKickedUser" invoke from server.
function Server_moderatorKickedUser(msgObj) {
	//addText("*Moderator " +  + " has kicked user " +  + ".", true);
}

// "msgCmds" is for remotely called chat commands. use msgObj.msgLower.
function Server_msgCmds(msgObj) {
	if (msgObj.event == "chatMsg") {
		//lobby commands here.

	}

	else if (msgObj.event == "doMessage" && msgObj.type == "secretMsg") {
		//pm commands here.

	}

}

// "oneToOneInviteAccepted" invoke from server.
function Server_oneToOneInviteAccepted(msgObj) {
	addColorText(Userlist.getParam(msgObj.from, Userlist.screenName) + " has accepted your invite.", "Green", true);
}

// "oneToOneInviteRejected" invoke from server.
function Server_oneToOneInviteRejected(msgObj) {
	addColorText(Userlist.getParam(msgObj.from, Userlist.screenName) + " has rejected your invite.", "Red", true);
}

// "setUserTable" invoke from server.
function Server_setUserTable(msgObj) {
	MyVars.myUserID = msgObj.userObj.userID;
	MyVars.myUserName = msgObj.userObj.userName;
	var chatObj;
	//debugObject("msgObj", msgObj);
	//debugObject("msgObj.userObj", msgObj.userObj);
	//debugObject("msgObj.userObj.client", msgObj.userObj.client);
	for (var i in msgObj.chatLog) {
		chatObj = msgObj.chatLog[i];
		chatObj.isBuffer = true;		
		Server_chatMsg(chatObj);
	}
}

// "startViewerVideo" invoke from server.
function Server_startViewerVideo(msgObj) {

}